import bcrypt
import time
from datetime import datetime, timedelta
from typing import Union, Annotated

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel
from tortoise.expressions import Q

from config.settings import TIME_FORMAT, SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES, REFRESH_TOKEN_EXPIRE_DAYS

from loguru import logger


class Token(BaseModel):
    id: int
    username: str
    roles: list = ["admin"]
    accessToken: str
    refreshToken: str
    expires: str


class User(BaseModel):
    id: int
    username: str
    disabled: Union[bool, None] = None


def gen_jwt(payload: dict, exp_minutes: datetime = datetime.now() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)):
    payload.update({"expire": exp_minutes.timestamp()})
    encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def verify_jwt(token: str) -> dict:
    """
    解析token
    :param token:  token
    :return:  解析后的数据 {'sub': 'admin', 'expire': 1704400202.9555986}
    """
    try:
        decoded_token = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return decoded_token if decoded_token["expire"] >= time.time() else None
    except JWTError as e:
        return {"error": e}


def hash_password(password: str) -> str:
    salt = bcrypt.gensalt()
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password.decode('utf-8')


def verify_password(password: str, hashed_password: str) -> bool:
    return bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8'))


